package top.lunarye.modules.award.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import top.lunarye.modules.award.entity.Award;
import top.lunarye.modules.award.entity.dto.*;
import top.lunarye.modules.award.mapper.AwardMapper;
import top.lunarye.modules.award.service.IAwardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import top.lunarye.modules.staff.entity.Staff;
import top.lunarye.utils.RestResponse;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 成果表  服务实现类
 * </p>
 *
 * @author lunar
 * @since 2021-07-23
 */
@Service("AwardServiceImpl")
public class AwardServiceImpl extends ServiceImpl<AwardMapper, Award> implements IAwardService {

    final AwardMapper awardMapper;

    public AwardServiceImpl(AwardMapper awardMapper) {
        this.awardMapper = awardMapper;
    }

    @Override
    public RestResponse analysisGroupByType() {
        List<AwardAnalysisTypeDTO> awardAnalysisTypeDTOS = awardMapper.analysisGroupByType();
        return RestResponse.ok(awardAnalysisTypeDTOS);
    }

    @Override
    public RestResponse analysisGroupByName() {
        List<AwardAnalysisNameDTO> awardAnalysisNameDTOS = awardMapper.analysisGroupByStaffName();
        return RestResponse.ok(awardAnalysisNameDTOS);
    }

    @Override
    public RestResponse<AwardAnalysisByNameDTO> analysisByName(String name, Integer current, Integer size) {
        List<AwardAnalysisNameDTO> awardAnalysisNameDTOS = awardMapper.analysisByName(name, (current-1) * size, size);
        Integer totalNum = awardMapper.getAnalysisByNameSize(name);
        return getAwardAnalysisByNameDTORestResponse(current, size, awardAnalysisNameDTOS, totalNum);
    }

    @Override
    public RestResponse<AwardAnalysisByNameDTO> analysisByNameLimitByDate(String name, Integer current, Integer size,
                                                                          Date startTime, Date endTime) {
        List<AwardAnalysisNameDTO> awardAnalysisNameDTOS = awardMapper.analysisByNameLimitByDate(name,
                (current-1) * size, size, startTime, endTime);
        Integer totalNum = awardMapper.getAnalysisByNameSizeLimitByDate(name,startTime, endTime);
        return getAwardAnalysisByNameDTORestResponse(current, size, awardAnalysisNameDTOS, totalNum);
    }

    private RestResponse<AwardAnalysisByNameDTO> getAwardAnalysisByNameDTORestResponse(Integer current, Integer size, List<AwardAnalysisNameDTO> awardAnalysisNameDTOS, Integer totalNum) {
        boolean hasNext, hasPre;
        hasNext = totalNum > current * size;
        hasPre = current != 1;
        AwardAnalysisByNameDTO awardAnalysisByNameDTO = new AwardAnalysisByNameDTO();
        awardAnalysisByNameDTO.setHasPre(hasPre);
        awardAnalysisByNameDTO.setHasNext(hasNext);
        awardAnalysisByNameDTO.setList(awardAnalysisNameDTOS);
        return RestResponse.ok(awardAnalysisByNameDTO);
    }

    public RestResponse analysisGroupByStaffNameLimitByDate(Date startTime, Date endTime) {
        List<AwardAnalysisNameDTO> awardAnalysisNameDTOS = awardMapper.analysisGroupByStaffNameLimitByDate(startTime, endTime);
        return RestResponse.ok(awardAnalysisNameDTOS);
    }

    public RestResponse analysisGroupByTypeLimitByDate(Date startTime, Date endTime) {
        List<AwardAnalysisTypeDTO> awardAnalysisNameDTOS = awardMapper.analysisGroupByTypeLimitByDate(startTime, endTime);
        return RestResponse.ok(awardAnalysisNameDTOS);
    }

    public RestResponse getStaffAwardsLimitByDatePage(Staff staff, Integer current, Integer size, Date startTime,
                                                  Date endTime) {
        QueryWrapper<Award> query = new QueryWrapper<>();
        query.lambda().between(Award::getGetTime, startTime, endTime).eq(Award::getStaffId, staff.getId());
        Page<Award> page = new Page<>(current, size);
        Page<Award> awardPage = awardMapper.selectPage(page, query);
        List<AwardSelectDTO> collect = awardPage.getRecords().stream().map(item -> {
            AwardSelectDTO awardSelectDTO = new AwardSelectDTO();
            BeanUtils.copyProperties(item, awardSelectDTO);
            awardSelectDTO.setStaffName(staff.getName());
            awardSelectDTO.setStaffId(staff.getId());
            return awardSelectDTO;
        }).collect(Collectors.toList());
        AwardPageDTO<List<AwardSelectDTO>> listAwardPageDTO = new AwardPageDTO<>();
        listAwardPageDTO.setHasNext(awardPage.hasNext());
        listAwardPageDTO.setHasPre(awardPage.hasPrevious());
        listAwardPageDTO.setAwardList(collect);
        return RestResponse.ok(listAwardPageDTO);
    }

    public RestResponse getStaffAwardsLimitByDate(Staff staff, Date startTime,
                                                      Date endTime) {
        QueryWrapper<Award> query = new QueryWrapper<>();
        query.lambda().between(Award::getGetTime, startTime, endTime).eq(Award::getStaffId, staff.getId());
        return getRestResponse(staff, query);
    }

    public RestResponse getStaffAwards(Staff staff) {
        QueryWrapper<Award> query = new QueryWrapper<>();
        query.lambda().eq(Award::getStaffId, staff.getId());
        return getRestResponse(staff, query);
    }

    private RestResponse getRestResponse(Staff staff, QueryWrapper<Award> query) {
        List<Award> awardList = awardMapper.selectList(query);
        List<AwardSelectDTO> collect = awardList.stream().map(item -> {
            AwardSelectDTO awardSelectDTO = new AwardSelectDTO();
            BeanUtils.copyProperties(item, awardSelectDTO);
            awardSelectDTO.setStaffName(staff.getName());
            awardSelectDTO.setStaffId(staff.getId());
            return awardSelectDTO;
        }).collect(Collectors.toList());
        return RestResponse.ok(collect);
    }

    public RestResponse getStaffAwardAnalysisLimitByDate(Staff staff, Date startTime, Date endTime) {
        List<AwardAnalysisTypeDTO> staffAwardAnalysisLimitByDate = awardMapper.getStaffAwardAnalysisLimitByDate(staff.getId(), startTime, endTime);
        return RestResponse.ok(staffAwardAnalysisLimitByDate);
    }

    public RestResponse getStaffAwardAnalysis(Staff staff) {
        List<AwardAnalysisTypeDTO> staffAwardAnalysisLimitByDate = awardMapper.getStaffAwardAnalysis(staff.getId());
        return RestResponse.ok(staffAwardAnalysisLimitByDate);
    }
}
